package com.creditrank.crcomponent;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Vector;


import com.creditrank.indexer.SeralizeHash;


/*
 * The code for CreditRank Calculator module goes in here
 * 
 * @author Swarnim Kulkarni
 * */

public class CRCalculator {
        
       /* Map<String,String> graph = new HashMap<String,String>();
        Map<String,String> invertedGraph = new HashMap<String,String>();
        Map<String,Double> goodScores = new HashMap<String,Double>();
        Map<String,Double> badScores = new HashMap<String,Double>();
        HashMap<String, Double> creditScores = new HashMap<String,Double>();
        Map<String, Double> pageRankScores = new HashMap<String,Double>();
        Map <String,String> id_url = new HashMap<String,String>();
        Map <String,Double> id_d = new HashMap<String,Double>();
	
        
        List<String> spam = new ArrayList<String>();
        List<String> nonspam = new ArrayList<String>();*/
	
		SerializeGraph sg= new SerializeGraph();
        
        static final double DEFAULT_SCORE = 1.0;
        static final double ALPHA = 0.85;
        static final int ITERATIONS = 70;
        
        CRCalculator(){
                
                //creditScores = new HashMap<Integer,Double>();
                //pageRankScores = new HashMap<String,Double>();
        }
        
        
        
        
       
        
        
        public void  invertGraph(){
                
                
                sg.invertedGraph.clear();
                String node="";
                String outlinks="";
                
                Set<String> tempKeySet;
                Iterator<String> tempNodeItr;
                String tempNode;
                String tempLinks;
                
                Set<String> keySet = sg.graph.keySet();
                Iterator<String> nodeItr = keySet.iterator();
                
                while(nodeItr.hasNext()){
                        
                        outlinks="";
                        node = nodeItr.next();
                        
                        tempKeySet = sg.graph.keySet();
                        tempNodeItr = tempKeySet.iterator();
                        
                        while(tempNodeItr.hasNext()){
                                
                                tempNode = tempNodeItr.next();
                                tempLinks = sg.graph.get(tempNode);
                                
                              //  if(tempLinks.trim().contains(node.trim())){
                                        
                                  //      outlinks = outlinks+" "+tempNode;
                                //}
                                
                                StringTokenizer st=new StringTokenizer(tempLinks.trim());
                                while(st.hasMoreTokens())
                                {
                                	if(node.trim().equals(st.nextToken()))
                                		outlinks = outlinks+" "+tempNode;
                                }
                        }                       
                        outlinks = outlinks.trim();                     
                        sg.invertedGraph.put(node, outlinks);                      
                }
                
                tempKeySet = sg.graph.keySet();
                tempNodeItr = tempKeySet.iterator();
                int count =0;
                while(tempNodeItr.hasNext()){
                    
                    tempNode = tempNodeItr.next();
                    tempLinks = sg.invertedGraph.get(tempNode);
                    if(tempLinks.equals(" ") || tempLinks.equals("")||tempLinks.equals("null"))
                    {
                    	count++;
                    }
                    
                }
                System.out.println("The count is : "+count);
                                
                       
        }
        
        
        
        public void calculateGoodScores(){
                
                Map<String,Double> tempMap = new HashMap<String,Double>();
                //Map<String,Double> goodScores = new HashMap<String,Double>();
                
                String node,node1;
                String linksList;
                String link;
                double fractionScore=0.0;
                double totalScore=0.0;
                
                double nonSpamRatio;
                double d;
                double temp_sum=0.0;
                boolean flag=false;
                sg.goodScores = initializeScores(sg.goodScores);
                //int i=0;
               // while(!flag){
                 for(int i=0;i<20;i++){       
                        Iterator<String> itr = sg.graph.keySet().iterator();
                        
                        tempMap.clear();
                        temp_sum=0.0;
                        while(itr.hasNext()){
                                
                                node = itr.next();
                                linksList = sg.invertedGraph.get(node);
                                
                               /* if(spam.contains(node))
                                        d=0;                                    
                                else                                    
                                        d=1;
                                */
                                d=sg.id_d.get(node);
                                StringTokenizer stk = new StringTokenizer(linksList);
                                fractionScore = 0.0;
                                totalScore = 0.0;
                                
                                while(stk.hasMoreTokens()){
                                        
                                        link = stk.nextToken();
                                        fractionScore += sg.goodScores.get(link)/noOfNodes(sg.graph.get(link));                                                                               
                                }
                                
                                nonSpamRatio = (double)(sg.nonspam.size())/sg.graph.size();
                                totalScore = ALPHA*fractionScore*nonSpamRatio+((1-ALPHA)*d);
                                //System.out.println(node + " Total Score scores :"+totalScore);
                                tempMap.put(node, totalScore);
                                temp_sum = temp_sum+totalScore;
                                //System.out.println("      "+temp_sum);
                                 
                        }
                        double c=1.0/temp_sum;
                       // System.out.println(c+"      "+temp_sum);
                        
                         
                        Iterator<String> itr1 = tempMap.keySet().iterator();
                        while(itr1.hasNext()){
                            
                            node1 = itr1.next();
                           	double rank1= c*(double)tempMap.get(node1);
                           	//System.out.println(node1+"   Normalized :"+rank1);
            				//page_scores_curr.remove(s);
            				//page_scores_curr.put(s, rank2);
                            //tempMap.remove(node1);
                           //	itr1.remove();
                           	tempMap.put(node1, rank1);
            				
                        }
                      /*  int count=0;
                        itr1 = tempMap.keySet().iterator();
                        while(itr1.hasNext()){
                            
                            node1 = itr1.next();
                            Double diff=(Double)sg.goodScores.get(node1)-(Double)tempMap.get(node1);

                            if(diff<0.0001)
            					count++;
            				//else
            					//flag=true;
                            if(count==tempMap.size())
                            	flag=true;
                            else
                            	flag=false;
                        }
                        i++;*/
                        sg.goodScores.clear();
                        sg.goodScores.putAll(tempMap);             // update scores
                        System.out.println("Good Ittr : "+i);
                }       
                                
               
                
        }
        
        public void calculateBadScores(){
                
                Map<String,Double> tempMap = new HashMap<String,Double>();
                //Map<String,Double> badScores = new HashMap<String,Double>();
                
                String node,node1;
                String linksList;
                String link;
                double fractionScore=0.0;
                double totalScore=0.0;
                double temp_sum=0.0;
                double totalSpamRatio;          // total spam / total links
                double localSpamRatio;          // links to spam from that node / total links from that node
                double d;
                boolean flag=false;
               // int i=0;
                sg.badScores = initializeScores(sg.badScores);
                
                //while(!flag){
                  for(int i=0; i< 20;i++){     
                        Iterator<String> itr = sg.graph.keySet().iterator();
                        
                        tempMap.clear();
                        
                        while(itr.hasNext()){
                                
                                node = itr.next();
                                linksList = sg.graph.get(node);
                                
                              /*  if(spam.contains(node))
                                        d=0;
                                else
                                        d=1;
                                */
                                
                                d=sg.id_d.get(node);
                                StringTokenizer stk = new StringTokenizer(linksList);
                                fractionScore = 0.0;
                                totalScore = 0.0;
                                
                                while(stk.hasMoreTokens()){
                                        
                                        link = stk.nextToken();
                                        if(sg.badScores.containsKey(link) && sg.invertedGraph.containsKey(link))
                                        fractionScore += sg.badScores.get(link)/noOfNodes(sg.invertedGraph.get(link));                                                                                
                                }
                               // System.out.println(node + " fractional scores ratio :"+fractionScore);
                                totalSpamRatio = (double)(sg.spam.size())/sg.graph.size();
                              //  System.out.println(node + " total spam ratio :"+totalSpamRatio);
                                int deno=noOfNodes(sg.graph.get(node));
                                int num=noOfSpamNodes(sg.graph.get(node));
                                if(deno==0 || num==0)
                                {
                                	localSpamRatio=0.0;
                                }
                                else
                                	localSpamRatio = (double)noOfSpamNodes(sg.graph.get(node))/noOfNodes(sg.graph.get(node));
                              //System.out.println(node + " local spam ratio :"+localSpamRatio);
                                totalScore = ALPHA*fractionScore*totalSpamRatio+((1-ALPHA)*(1-d)*localSpamRatio);
                               
                                tempMap.put(node, totalScore);
                                temp_sum=temp_sum+totalScore;
                                
                                 
                        }
                        double c=1.0/temp_sum;
                        temp_sum=0.0;
                        Iterator<String> itr1 = tempMap.keySet().iterator();
                        while(itr1.hasNext()){
                            
                            node1 = itr1.next();
                           	Double rank1= c*tempMap.get(node1);
            				//page_scores_curr.remove(s);
            				//page_scores_curr.put(s, rank2);
                           // tempMap.remove(node1);
                            tempMap.put(node1, rank1);
            				
                        }
                       /* itr1 = tempMap.keySet().iterator();
                        int count=0;
                        while(itr1.hasNext()){
                            
                            
                        	node1 = itr1.next();
                            node1 = itr1.next();
                            Double diff=(Double)sg.badScores.get(node1)-(Double)tempMap.get(node1);

                            if(diff<0.0001)
            					count++;
            				//else
            					//flag=true;
                            if(count==tempMap.size())
                            	flag=true;
                            else
                            	flag=false;
                           	
            				
                        }*/
                       // i++;
                        sg.badScores.clear();
                        sg.badScores.putAll(tempMap);              // update scores
                        System.out.println("Bad Ittr : "+i);
                }       
                                
                //return sg.badScores;
                
        }
        /*
        Map<String,Double> calculatePageScores(Map<String,String> graph, Map<String,String> invertedGraph){
                
                Map<String,Double> tempMap = new HashMap<String,Double>();
                Map<String,Double> pageScores = new HashMap<String,Double>();
                
                String node;
                String linksList;
                String link;
                double fractionScore=0.0;
                double totalScore=0.0;          
                
                pageScores = initializeScores(pageScores,graph);
                
                for(int i=0;i<ITERATIONS;i++){
                        
                        Iterator<String> itr = graph.keySet().iterator();
                        
                        tempMap.clear();
                        
                        while(itr.hasNext()){
                                
                                node = itr.next();
                                linksList = invertedGraph.get(node);
                                                                                                                                        
                                StringTokenizer stk = new StringTokenizer(linksList);
                                fractionScore = 0.0;
                                totalScore = 0.0;
                                
                                while(stk.hasMoreTokens()){
                                        
                                        link = stk.nextToken();
                                        fractionScore += pageScores.get(link)/noOfNodes(graph.get(link));                                                                               
                                }
                                totalScore = ALPHA*fractionScore+((1-ALPHA)/graph.size());
                                tempMap.put(node, totalScore);
                                 
                        }
                        pageScores.clear();
                        pageScores.putAll(tempMap);             // update scores
                }       
                                
                return pageScores;
                
        }
        */
        int noOfNodes(String list){
                                
                StringTokenizer stk = new StringTokenizer(list);
                int count=0;
                while(stk.hasMoreTokens())
                {
                	if(sg.id_url.containsKey(stk.nextToken().trim()))
                		count++;
                }
                return count;
        }
        
        int noOfSpamNodes(String list){
                
                int count=0;
                
                StringTokenizer stk = new StringTokenizer(list);
                
                while(stk.hasMoreTokens()){
                        if(sg.spam.contains(stk.nextToken()))
                                count++;
                }
                return count;
        }
        
        private Map<String,Double> initializeScores(Map<String,Double> scores){
                
                Set<String> keySet = sg.graph.keySet();
                Iterator<String> nodeItr = keySet.iterator();
                
                scores.clear();
                while(nodeItr.hasNext()){
                        
                        scores.put(nodeItr.next().trim(), DEFAULT_SCORE);
                }
                
                return scores;
                
        }
        
        
        void readData() {
        	SeralizeHash sh;
        	sg.graph.clear();
        	sg.id_url.clear();
        	sg.id_d.clear();
        	sg.spam.clear();
        	sg.nonspam.clear();
            try {
                
            	 for(int i=1;i<=5;i++)
            	 {
            		 System.out.println(i);
            		FileInputStream in = new FileInputStream("Code1/Serialized"+i+ ".txt");
               
                    ObjectInputStream sin = new ObjectInputStream(in);
                  
                        sh = (SeralizeHash) sin.readObject();
                        System.out.println(sh.outgoing.size());
                        Set<String> keySet = sh.outgoing.keySet();
                        Iterator<String> nodeItr = keySet.iterator();
                        
                        
                        while(nodeItr.hasNext()){
                        	String node= nodeItr.next();
                        	LinkedList<String> l= sh.outgoing.get(node);
                        	sg.id_url.put(node, l.get(0));
                        	sg.graph.put(node, l.get(1));
                        	double d = Double.parseDouble(l.get(2));
                        	sg.id_d.put(node, d);
                        	if(d<0.5)
                        	{
                        		
                        		if(!sg.nonspam.contains(node) && !sg.spam.contains(node))
                        			sg.spam.add(node);
                        	}
                        	else
                        	{
                        		if(!sg.spam.contains(node)&& !sg.nonspam.contains(node))
                        			sg.nonspam.add(node);
                        	}
                        	
                        	
                        	
                        }
                       
                        sin.close();
                        in.close();
            	 }

                 } catch (Exception e) {
                        e.printStackTrace();
                 }
               /* 
                 System.out.println(graph.size());
                 System.out.println(nonspam.size());
                 System.out.println(spam.size());
                 Iterator<String> nodeItr = spam.iterator();
                 
                 while(nodeItr.hasNext()){
                	 if(nonspam.contains(nodeItr.next()))
                			 System.out.println("There..");
                 }
                 
                    */
            }

//  TODO: insert function to sort hashtable automatically by value
        public void insertDb()
        {
        	String node="",url="", outgoing="",incoming="";
        	Double goodscore=0.0,badscore=0.0,creditscore=0.0;
        	Statement stmt;
        	int rows;
        	//System.out.println("Hello...");
        	String dbUrl = "jdbc:mysql://mysql.cis.ksu.edu:3306/sudhikrr";
    		//long i=1;
    		try
    		{
        		Class.forName("com.mysql.jdbc.Driver");
    			Connection con = DriverManager.getConnection (dbUrl,"sudhikrr","40Vlf0bK");
    			Set<String> keySet = sg.id_url.keySet();
                Iterator<String> nodeItr = keySet.iterator();
                
                
                while(nodeItr.hasNext())
               {
                	node=nodeItr.next();
                	url=sg.id_url.get(node);
                	outgoing=sg.graph.get(node);
                	incoming=sg.invertedGraph.get(node);
                	goodscore=sg.goodScores.get(node);
                	badscore=sg.badScores.get(node);
                	creditscore=goodscore-badscore;
                	System.out.println(goodscore +"   B: "+ badscore+"   C "+creditscore);
    			
    			//String sql = "INSERT INTO  scores values ("+node+","+url+","+outgoing+","+incoming+","+goodscore+","+badscore+","+creditscore+")";
    			
    			//stmt = con.createStatement(); 
    			//rows = stmt.executeUpdate(sql); 

				//String sql = "SELECT id,text FROM test2 where id="+j;
    			
    			PreparedStatement prep = con.prepareStatement(
    		      "INSERT INTO  scores1 values(?,?,?,?,?,?,?)");

    		    prep.setString(1, node);
    		    prep.setString(2, url);
    		    prep.setString(3, outgoing);
    		    prep.setString(4, incoming);
    		    prep.setDouble(5, goodscore);
    		    prep.setDouble(6, badscore);
    		    prep.setDouble(7, creditscore);
				prep.executeUpdate();
			
					
					
				}
                
                con.close();
    		}
    		catch(Exception e)
    		{
    			e.printStackTrace();
    		}
        }
        
        
        public void serialize_graph(String s,SerializeGraph sg) throws IOException
    	{
    		String file="";
        	if(s.equals("inv"))
    			file="Code1/SerialHashtables/Serial_inverted_graph.txt";
        	else if(s.equals("Good"))
        		file="Code1/SerialHashtables/Serial_good_score.txt";
        	else if(s.equals("Bad"))
        		file="Code1/SerialHashtables/Serial_bad_score.txt";
        		
        	FileOutputStream fos = new FileOutputStream( file );
    		ObjectOutputStream outStream =new ObjectOutputStream( fos );
    		
    	      //  Save each object.
    	      outStream.writeObject( sg );
    	      outStream.close();

    	     

    	}
        public static void main(String args[]) throws IOException{
                
                CRCalculator cr1 = new CRCalculator();
                System.out.println("Loading Graph...");
                cr1.readData();
                System.out.println(cr1.sg.graph.size());
             
              //  cr1.spam = cr1.initializeSpam();
               // cr1.graph = cr1.readGraph("data/Graph.txt");
                System.out.println("computing inverted Graph...");
                cr1.invertGraph();
                cr1.serialize_graph("inv", cr1.sg);
                System.out.println(cr1.sg.invertedGraph.size());
                System.out.println("Calculating good scores...");
               cr1.calculateGoodScores();
               cr1.serialize_graph("Good", cr1.sg);
               System.out.println(cr1.sg.goodScores.size());
               System.out.println("Calculating bad scores...");
                cr1.calculateBadScores();
                cr1.serialize_graph("Bad", cr1.sg);
                System.out.println(cr1.sg.badScores.size());
                System.out.println("Inserting into data base...");
                cr1.insertDb();
                
                /*cr1.pageRankScores = cr1.calculatePageScores(cr1.graph, cr1.invertedGraph);
                
                                
                for(int i=0;i<cr1.graph.size();i++){
                                                
                        cr1.creditScores.put(i, cr1.goodScores.get(Integer.toString(i))-cr1.badScores.get(Integer.toString(i)));
                }
                
                Iterator<Integer> itr = cr1.creditScores.keySet().iterator();
                int node;
                
                while(itr.hasNext()){
                        
                        node = itr.next();                      
                                                
                        if(cr1.spam.contains(((Integer)node).toString()))
                                System.out.println(node+","+cr1.creditScores.get(node)+"  <---");
                        else
                                System.out.println(node+","+cr1.creditScores.get(node));
                        
                }
                
                System.out.println();
                System.out.println("*****************************");
                System.out.println("PageRank Scores :");
                System.out.println("*****************************");
                Iterator<String> itr1 = cr1.pageRankScores.keySet().iterator();
                String node1;
                
                while(itr1.hasNext()){
                        
                        node1 = itr1.next();                    
                                                                        
                        if(cr1.spam.contains(node1.trim()))
                                System.out.println(node1+","+cr1.pageRankScores.get(node1)+"  <---");
                        else
                                System.out.println(node1+","+cr1.pageRankScores.get(node1));
                        
                }
                */
        }       
}
